package com.petdog.module.admin.controller;

import com.petdog.infrastructure.entity.AdminOperationLog;
import com.petdog.module.admin.dto.AdminDashboardDto;
import com.petdog.module.admin.dto.AdminLoginRequest;
import com.petdog.module.admin.dto.OperationLogQueryRequest;
import com.petdog.module.admin.service.AdminService;
import com.petdog.common.dto.ApiResponse;
import com.petdog.common.dto.PageResult;
import com.petdog.common.util.AdminAuthUtil;
import lombok.RequiredArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.Map;

import com.petdog.infrastructure.entity.BreedInfo;
import org.springframework.web.multipart.MultipartFile;

/**
 * 管理员控制器
 */
@RestController
@RequestMapping("/api/admin")
public class AdminController {

    private static final Logger log = LoggerFactory.getLogger(AdminController.class);

    @Autowired
    private AdminService adminService;

    /**
     * 获取数据看板（默认近7天数据）
     */
    @GetMapping("/dashboard")
    public ApiResponse<AdminDashboardDto> getDashboardData(HttpServletRequest request) {
        try {
            AdminDashboardDto dashboardData = adminService.getDashboardData();
            saveOperationLog(request, "dashboard", "view", "查看数据看板");
            return ApiResponse.success(dashboardData);
        } catch (Exception e) {
            log.error("获取数据看板失败", e);
            return ApiResponse.error(500, "获取数据看板失败");
        }
    }

    /**
     * 获取指定时间范围的核心统计数据
     */
    @GetMapping("/dashboard/statistics")
    public ApiResponse<AdminDashboardDto> getDashboardStatistics(
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            @RequestParam(required = false, defaultValue = "all") String indicators,
            HttpServletRequest request) {
        try {
            // 如果没有提供日期范围，设置默认值（近7天）
            LocalDate today = LocalDate.now();
            if (startDate == null) {
                startDate = today.minusDays(6);
            }
            if (endDate == null) {
                endDate = today;
            }

            AdminDashboardDto dashboardData = adminService.getDashboardDataByTimeRange(startDate, endDate, indicators);
            saveOperationLog(request, "dashboard", "statistics", 
                    String.format("查看指定时间范围数据: %s 至 %s, 指标类型: %s", 
                            startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 
                            endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 
                            indicators));
            return ApiResponse.success(dashboardData);
        } catch (IllegalArgumentException e) {
            log.error("参数验证失败: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (RuntimeException e) {
            log.error("获取数据失败: {}", e.getMessage());
            return ApiResponse.error(500, e.getMessage());
        } catch (Exception e) {
            log.error("获取指定时间范围数据失败", e);
            return ApiResponse.error(500, "数据加载失败，请刷新页面重试");
        }
    }

    /**
     * 导出指定时间范围的数据为Excel
     */
    @PostMapping("/dashboard/export")
    public void exportDashboardData(
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @RequestParam(required = false) @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            @RequestParam(required = false, defaultValue = "all") String dataType,
            HttpServletRequest request,
            HttpServletResponse response) {
        try {
            // 如果没有提供日期范围，设置默认值（近7天）
            LocalDate today = LocalDate.now();
            if (startDate == null) {
                startDate = today.minusDays(6);
            }
            if (endDate == null) {
                endDate = today;
            }

            adminService.exportDashboardData(startDate, endDate, dataType, response);
            saveOperationLog(request, "dashboard", "export", 
                    String.format("导出数据: %s 至 %s, 数据类型: %s", 
                            startDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 
                            endDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd")), 
                            dataType));
        } catch (IllegalArgumentException e) {
            log.error("导出参数验证失败: {}", e.getMessage());
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            try {
                response.getWriter().write("{\"code\": 400, \"message\": \"" + e.getMessage() + "\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        } catch (RuntimeException e) {
            log.error("导出失败: {}", e.getMessage());
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("{\"code\": 500, \"message\": \"" + e.getMessage() + "\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        } catch (Exception e) {
            log.error("数据导出失败", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("{\"code\": 500, \"message\": \"文件导出异常，请检查数据量或稍后重试\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        }
    }

    /**
     * 获取用户列表
     */
    @GetMapping("/users")
    public ApiResponse<PageResult> getUserList(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) String username,
            @RequestParam(required = false) String email,
            @RequestParam(required = false) Integer status,
            HttpServletRequest request) {
        try {
            PageResult result = adminService.getUserList(pageNum, pageSize, username, email, status);
            saveOperationLog(request, "user", "list", "获取用户列表");
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取用户列表失败", e);
            return ApiResponse.error(500, "获取用户列表失败");
        }
    }

    /**
     * 更新用户状态
     */
    @PutMapping("/users/{userId}/status")
    public ApiResponse<Boolean> updateUserStatus(
            @PathVariable Long userId,
            @RequestBody Map<String, Integer> requestBody,
            HttpServletRequest request) {
        try {
            Integer status = requestBody.get("status");
            boolean success = adminService.updateUserStatus(userId, status);
            saveOperationLog(request, "user", "status", "更新用户状态: 用户ID=" + userId + ", 状态=" + status);
            return ApiResponse.success(success);
        } catch (Exception e) {
            log.error("更新用户状态失败", e);
            return ApiResponse.error(500, "更新用户状态失败");
        }
    }

    /**
     * 重置用户密码
     */
    @PutMapping("/users/{userId}/reset-password")
    public ApiResponse<Boolean> resetUserPassword(
            @PathVariable Long userId,
            HttpServletRequest request) {
        try {
            boolean success = adminService.resetUserPassword(userId);
            saveOperationLog(request, "user", "reset-password", "重置用户密码: 用户ID=" + userId);
            return ApiResponse.success(success);
        } catch (Exception e) {
            log.error("重置用户密码失败", e);
            return ApiResponse.error(500, "重置用户密码失败");
        }
    }

    /**
     * 获取内容审核列表
     */
    @GetMapping("/review")
    public ApiResponse<PageResult> getContentReviewList(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(defaultValue = "post") String contentType,
            @RequestParam(required = false) Integer status,
            HttpServletRequest request) {
        try {
            // 验证管理员权限
            if (!AdminAuthUtil.validateAdminRequest(request)) {
                return ApiResponse.error(403, "无管理员权限，无法执行内容管控操作");
            }
            
            PageResult result = adminService.getContentReviewList(pageNum, pageSize, contentType, status);
            saveOperationLog(request, "review", "list", "获取内容审核列表: 类型=" + contentType);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取内容审核列表失败", e);
            return ApiResponse.error(500, "获取内容审核列表失败");
        }
    }

    /**
     * 审核内容
     */
    @PutMapping("/review/{contentId}")
    public ApiResponse<Boolean> reviewContent(
            @PathVariable Long contentId,
            @RequestBody Map<String, Object> requestBody,
            HttpServletRequest request) {
        try {
            // 验证管理员权限
            if (!AdminAuthUtil.validateAdminRequest(request)) {
                return ApiResponse.error(403, "无管理员权限，无法执行内容管控操作");
            }
            
            String contentType = (String) requestBody.get("contentType");
            Integer status = (Integer) requestBody.get("status");
            String reviewNote = (String) requestBody.get("reviewNote");
            
            boolean success = adminService.reviewContent(contentId, contentType, status, reviewNote);
            saveOperationLog(request, "review", "process", "审核内容: ID=" + contentId + ", 类型=" + contentType + ", 状态=" + status);
            return ApiResponse.success(success);
        } catch (IllegalArgumentException e) {
            log.error("审核内容参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("审核内容失败", e);
            return ApiResponse.error(500, "审核内容失败");
        }
    }
    
    /**
     * 编辑内容文本
     */
    @PutMapping("/content/edit")
    public ApiResponse<Boolean> editContent(
            @RequestBody Map<String, Object> requestBody,
            HttpServletRequest request) {
        try {
            // 验证管理员权限
            if (!AdminAuthUtil.validateAdminRequest(request)) {
                return ApiResponse.error(403, "无管理员权限，无法执行内容管控操作");
            }
            
            Long contentId = ((Number) requestBody.get("contentId")).longValue();
            String contentType = (String) requestBody.get("contentType");
            String editedContent = (String) requestBody.get("content");
            
            boolean success = adminService.editContent(contentId, contentType, editedContent);
            saveOperationLog(request, "content", "edit", "编辑内容: ID=" + contentId + ", 类型=" + contentType);
            return ApiResponse.success(success);
        } catch (IllegalArgumentException e) {
            log.error("编辑内容参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("编辑内容失败", e);
            return ApiResponse.error(500, "编辑内容失败");
        }
    }
    
    /**
     * 删除内容（支持单条或批量）
     */
    @DeleteMapping("/content/delete")
    public ApiResponse<Boolean> deleteContent(
            @RequestBody Map<String, Object> requestBody,
            HttpServletRequest request) {
        try {
            // 验证管理员权限
            if (!AdminAuthUtil.validateAdminRequest(request)) {
                return ApiResponse.error(403, "无管理员权限，无法执行内容管控操作");
            }
            
            @SuppressWarnings("unchecked")
            List<Long> contentIds = (List<Long>) requestBody.get("contentIds");
            String contentType = (String) requestBody.get("contentType");
            String deleteReason = (String) requestBody.get("deleteReason");
            
            boolean success = adminService.deleteContent(contentIds, contentType, deleteReason);
            saveOperationLog(request, "content", "delete", "删除内容: 数量=" + contentIds.size() + ", 类型=" + contentType);
            return ApiResponse.success(success);
        } catch (IllegalArgumentException e) {
            log.error("删除内容参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("删除内容失败", e);
            return ApiResponse.error(500, "删除内容失败");
        }
    }

    /**
     * 获取操作日志列表（仅超级管理员或审计员可访问）
     */
    @PostMapping("/logs")
    public ApiResponse<PageResult<AdminOperationLog>> getOperationLogList(
            @RequestBody OperationLogQueryRequest request,
            HttpServletRequest servletRequest) {
        try {
            // 验证是否有审计权限
            if (!AdminAuthUtil.validateAuditRequest(servletRequest)) {
                log.warn("非权限用户尝试查询操作日志");
                return ApiResponse.error(403, "无日志审计权限，仅超级管理员或审计员可操作");
            }
            
            // 验证查询条件
            if (request.getStartTime() != null && request.getEndTime() != null && 
                request.getStartTime().isAfter(request.getEndTime())) {
                return ApiResponse.error(400, "查询条件不合法（时间范围倒序），请修正后重试");
            }
            
            PageResult<AdminOperationLog> result = adminService.getOperationLogList(request);
            saveOperationLog(servletRequest, "log", "list", "获取操作日志列表");
            return ApiResponse.success(result);
        } catch (IllegalArgumentException e) {
            log.error("操作日志查询参数错误: {}", e.getMessage());
            return ApiResponse.error(400, "查询条件不合法，请修正后重试");
        } catch (Exception e) {
            log.error("获取操作日志列表失败", e);
            return ApiResponse.error(500, "获取操作日志列表失败");
        }
    }

    /**
     * 导出操作日志为CSV文件（仅超级管理员或审计员可访问）
     */
    @PostMapping("/logs/export-csv")
    public void exportOperationLogs(
            @RequestBody OperationLogQueryRequest request,
            HttpServletRequest servletRequest,
            HttpServletResponse response) {
        try {
            // 验证是否有审计权限
            if (!AdminAuthUtil.validateAuditRequest(servletRequest)) {
                log.warn("非权限用户尝试导出操作日志");
                response.setStatus(HttpServletResponse.SC_FORBIDDEN);
                response.getWriter().write("{\"code\": 403, \"message\": \"无日志审计权限，仅超级管理员或审计员可操作\"}");
                return;
            }
            
            // 验证查询条件
            if (request.getStartTime() != null && request.getEndTime() != null && 
                request.getStartTime().isAfter(request.getEndTime())) {
                response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
                response.getWriter().write("{\"code\": 400, \"message\": \"查询条件不合法（时间范围倒序），请修正后重试\"}");
                return;
            }
            
            adminService.exportOperationLogsToCSV(request, response);
            saveOperationLog(servletRequest, "log", "export", "导出操作日志为CSV文件");
        } catch (IllegalArgumentException e) {
            log.error("操作日志导出参数错误: {}", e.getMessage());
            response.setStatus(HttpServletResponse.SC_BAD_REQUEST);
            try {
                response.getWriter().write("{\"code\": 400, \"message\": \"查询条件不合法，请修正后重试\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        } catch (IOException e) {
            log.error("日志导出失败: {}", e.getMessage());
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("{\"code\": 500, \"message\": \"日志导出失败（可能因数据量过大或网络问题），请重试或缩小查询范围\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        } catch (Exception e) {
            log.error("日志导出系统异常", e);
            response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
            try {
                response.getWriter().write("{\"code\": 500, \"message\": \"日志导出失败，请联系技术人员处理\"}");
            } catch (Exception ex) {
                log.error("响应异常", ex);
            }
        }
    }
    
    /**
     * 保存操作日志
     */
    private void saveOperationLog(HttpServletRequest request, String module, String type, String desc) {
        try {
            AdminOperationLog log = new AdminOperationLog();
            // 这里假设管理员ID和用户名可以从请求中获取
            // 实际项目中应从认证信息中获取
            log.setAdminId(1L); // 示例值
            log.setAdminUsername("admin"); // 示例值
            log.setOperationType(type);
            log.setOperationModule(module);
            log.setOperationDesc(desc);
            log.setRequestParams("{}");
            log.setRequestIp(getIpAddress(request));
            log.setUserAgent(request.getHeader("User-Agent"));
            log.setStatus(1);
            adminService.saveOperationLog(log);
        } catch (Exception e) {
            log.error("保存操作日志失败", e);
        }
    }

    /**
     * 获取请求IP地址
     */
    private String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        return ip;
    }

    // 以下是品种知识库维护相关的API接口

    /**
     * 获取品种列表（支持分页、搜索、筛选）
     */
    @GetMapping("/breeds")
    public ApiResponse<PageResult> getBreedList(
            @RequestParam(defaultValue = "1") Integer pageNum,
            @RequestParam(defaultValue = "10") Integer pageSize,
            @RequestParam(required = false) String keyword,
            @RequestParam(required = false) String sizeCategory,
            HttpServletRequest request) {
        try {
            PageResult result = adminService.getBreedList(pageNum, pageSize, keyword, sizeCategory);
            saveOperationLog(request, "breed", "list", 
                    "获取品种列表: 页码=" + pageNum + ", 每页数量=" + pageSize + ", 关键词=" + keyword);
            return ApiResponse.success(result);
        } catch (Exception e) {
            log.error("获取品种列表失败", e);
            return ApiResponse.error(500, "获取品种列表失败");
        }
    }

    /**
     * 创建新品种
     */
    @PostMapping("/breeds")
    public ApiResponse<Boolean> createBreed(
            BreedInfo breedInfo,
            @RequestPart(required = true) List<MultipartFile> images,
            HttpServletRequest request) {
        try {
            boolean success = adminService.createBreed(breedInfo, images);
            saveOperationLog(request, "breed", "create", 
                    "创建新品种: 名称=" + breedInfo.getBreedName());
            return ApiResponse.success(success, "创建成功");
        } catch (IllegalArgumentException e) {
            log.error("创建品种参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("创建品种失败", e);
            return ApiResponse.error(500, "创建品种失败");
        }
    }

    /**
     * 更新品种信息
     */
    @PutMapping("/breeds/{id}")
    public ApiResponse<Boolean> updateBreed(
            @PathVariable Integer id,
            BreedInfo breedInfo,
            @RequestPart(required = false) List<MultipartFile> images,
            HttpServletRequest request) {
        try {
            boolean success = adminService.updateBreed(id, breedInfo, images);
            saveOperationLog(request, "breed", "update", 
                    "更新品种: ID=" + id + ", 名称=" + breedInfo.getBreedName());
            return ApiResponse.success(success, "更新成功");
        } catch (IllegalArgumentException e) {
            log.error("更新品种参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("更新品种失败", e);
            return ApiResponse.error(500, "更新品种失败");
        }
    }

    /**
     * 删除品种
     */
    @DeleteMapping("/breeds/{id}")
    public ApiResponse<Boolean> deleteBreed(
            @PathVariable Integer id,
            HttpServletRequest request) {
        try {
            boolean success = adminService.deleteBreed(id);
            saveOperationLog(request, "breed", "delete", 
                    "删除品种: ID=" + id);
            return ApiResponse.success(success, "删除成功");
        } catch (IllegalArgumentException e) {
            log.error("删除品种参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("删除品种失败", e);
            return ApiResponse.error(500, e.getMessage());
        }
    }

    /**
     * 批量导入品种（从CSV文件）
     */
    @PostMapping("/breeds/batch-import")
    public ApiResponse<Map<String, Object>> batchImportBreeds(
            @RequestPart("file") MultipartFile csvFile,
            HttpServletRequest request) {
        try {
            Map<String, Object> result = adminService.batchImportBreeds(csvFile);
            saveOperationLog(request, "breed", "batch-import", 
                    "批量导入品种: 总数量=" + result.get("totalCount") + ", 成功=" + result.get("successCount") + ", 失败=" + result.get("failCount"));
            return ApiResponse.success(result);
        } catch (IllegalArgumentException e) {
            log.error("批量导入品种参数错误: {}", e.getMessage());
            return ApiResponse.error(400, e.getMessage());
        } catch (Exception e) {
            log.error("批量导入品种失败", e);
            return ApiResponse.error(500, "批量导入品种失败");
        }
    }

    /**
     * 检查品种名称是否已存在
     */
    @GetMapping("/breeds/check-name")
    public ApiResponse<Boolean> checkBreedNameExists(
            @RequestParam String name,
            @RequestParam(required = false) Integer excludeId) {
        try {
            boolean exists = adminService.checkBreedNameExists(name, excludeId);
            return ApiResponse.success(exists);
        } catch (Exception e) {
            log.error("检查品种名称是否存在失败", e);
            return ApiResponse.error(500, "检查失败");
        }
    }

    /**
     * 获取所有体型分类选项
     */
    @GetMapping("/breeds/size-categories")
    public ApiResponse<List<String>> getSizeCategories() {
        try {
            List<String> categories = adminService.getSizeCategories();
            return ApiResponse.success(categories);
        } catch (Exception e) {
            log.error("获取体型分类失败", e);
            return ApiResponse.error(500, "获取失败");
        }
    }
}
